(function () {
    var IO_DATA = {
		_commKey : null,		//res加密公钥所用到的key
		token : null,			//玩家token，在连接初始化时用于res生成公钥
		jwtToken : null,		//res加密之后的玩家token，数据交互以此token为主
		publicKey : null,		//res公钥
		connectionUrl : null,	//连接url
		encryptedString : null,	//res加密后的验证字符串
	};
    var cmd = {
		CONN_INIT : "conn::init",			//连接初始化，用来更新jwt token
		CONN_ERROR : "conn::error",			//服务端异常

		TEST_PING : "test::ping",			//测试用命令
		TEST_PONG : "test::pong"			//测试用命令
	};

    function IO() {
		IO.super(this);

        this.primus = null;
		this.isOpened = false;//连接是否已经初始化过

		this.register("conn::init", this, this.onConnInit);
		this.register("io.error", this, this.onError);
		this.register("io.reconnect", this, this.onReconnect);
		this.register("io.end", this, this.onEnd);
		this.register("io.open", this, this.onIOOpen);
    }
    Laya.class(IO, "Libs.IO", Libs.Viewer);
    var _proto = IO.prototype;

    //生成commkey
	_proto.generateCommKey = function(){
		try{
			//默认32位编码
			IO_DATA._commKey = Date.now().toString() + Date.now().toString() + Date.now().toString().substring(0,6);
		}catch(e){
			console.log("初始化commKey失败",e);
		}
	}

	//生成encryptedString
	_proto.generateEncryptedString = function(){
		try{
			var params = "jwt=" + IO_DATA.token + "&commKey=" + IO_DATA._commKey;
			var jsencrypt = new JSEncrypt();
			jsencrypt.setPublicKey(IO_DATA.publicKey);
			IO_DATA.encryptedString = jsencrypt.encrypt(params);
		}catch(e){
			console.log("初始化encryptedString失败",e);
		}
	}
	_proto.onOpen = function(){
		//防止reconnect之后重复触发open，以下事件只绑定一次
		if(this.isOpened){ return; }
		this.isOpened = true;
		//触发open
		this.publish("io.open");

		this.primus.on('data', this.onData.bind(this));

		this.primus.on('error', function (data) {
			this.publish("io.error", data);
		}.bind(this));

		this.primus.on('reconnect', function () {
			this.publish("io.reconnect");
		}.bind(this));

		this.primus.on('end', function () {
			this.publish("io.end");
		}.bind(this));
	}
	_proto.onData = function(data){
		//解密
        var decryptstr = CryptoJS.AES.decrypt(data, CryptoJS.enc.Utf8.parse(IO_DATA._commKey), {
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7
        });

        var dataString = decryptstr.toString(CryptoJS.enc.Utf8);
        var parsedData = JSON.parse(dataString);
		if(parsedData.cmd != "monster::move" && parsedData.cmd != "move::move"){
        	console.log("接收到数据：\n" + parsedData.cmd,JSON.stringify(parsedData));
		}
        //更新jwt token
        if(parsedData.cmd == cmd.CONN_INIT){
        	IO_DATA.jwtToken = parsedData.res;
        }

		this.publish(parsedData.cmd, parsedData.res);
	}
	_proto.onError = function (data) {
		console.log("连接出错");
	}
	_proto.onReconnect = function () {
		console.log("重连中");
	}
	_proto.onEnd = function(){
		console.log("连接已关闭");
	}
	_proto.onConnInit = function () {
		console.log("成功初始化连接");
	}
	_proto.onIOOpen = function () {
		console.log("连接成功");
	}

	_proto.connect = function(config){
		$.extend(IO_DATA, config);

		this.generateCommKey();
		this.generateEncryptedString();

		try{
			this.primus = Primus.connect(IO_DATA.connectionUrl);

			this.primus.on('outgoing::url', function(url){
	            url.query = 'login=' + IO_DATA.encryptedString;
				console.log("outgoing::url",url.query);
	        });

	        this.primus.on('open', this.onOpen.bind(this));
		}
		catch(e){
			console.log(e);
		}
	}
	_proto.emit = function(data){
		//为data增加token
		if(data.params){
			data.params.jwt = IO_DATA.jwtToken;
		}else{
			data.params = { jwt : IO_DATA.jwtToken };
		}

		data.status = { time : Date.now() };

		console.log("发送数据：",JSON.stringify(data));

		//加密
		var encryptData = CryptoJS.AES.encrypt(JSON.stringify(data), CryptoJS.enc.Utf8.parse(IO_DATA._commKey), {
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7
        });
        //发送加密数据
		this.primus.write(encryptData.toString());
	}
	//手动断开连接
	_proto.end = function(){
		this.primus && this.primus.end();
	}
})();